package com.zyt.wiki.controller;

import com.zyt.wiki.exception.BusinessException;
import com.zyt.wiki.exception.BusinessExceptionCode;
import com.zyt.wiki.req.EbookQueryReq;
import com.zyt.wiki.req.EbookSaveReq;
import com.zyt.wiki.resp.CommonResp;
import com.zyt.wiki.resp.EbookQueryResp;
import com.zyt.wiki.resp.PageResp;
import com.zyt.wiki.service.EbookService;
import com.zyt.wiki.util.FileUtil;
import com.zyt.wiki.util.LoginUserContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.validation.Valid;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

@RestController
@RequestMapping("/ebook")
public class EbookController {

    public static final Logger LOG = LoggerFactory.getLogger(EbookController.class) ;

    @Value("${file.upload.path.temp}")
    private String tempFilePath ;   // 临时文件目录

    @Value("${file.upload.path.work}")
    private String workFilePath ;   // 最终文件目录

    @Autowired
    private EbookService ebookService ;

    // Get：http://localhost:8880/ebook/list?name=Vue ， 其中的name会映射到EbookReq中的同名属性
    // Get：http://localhost:8880/ebook/list?pageNum=2&pageSize=2 ， 其中的name会映射到EbookReq中的同名属性
    @GetMapping("/list")
    public CommonResp list(@Valid EbookQueryReq req){
        CommonResp<PageResp<EbookQueryResp>> resp = new CommonResp<>() ;
        PageResp<EbookQueryResp> pageResp = this.ebookService.list(req) ;
        resp.setContent(pageResp);
        return resp ;
    }

    // Get：http://localhost:8880/ebook/all  或   http://localhost:8880/ebook/all?category2Id=101
    @GetMapping("/all")
    public CommonResp all(EbookQueryReq req){
        CommonResp<List<EbookQueryResp>> resp = new CommonResp<>() ;
        List<EbookQueryResp> list = this.ebookService.all(req);
        resp.setContent(list);
        return resp ;
    }

    // 【POST提交时】注意：
    //      前端若是application/x-www-form-urlencoded表单提交，则参数前面不用@RequestBody也能正常映射到参数；
    //      若是application/json方式提交，则需要@RequestBody把参数接收进来
    // axios的post提交，是用application/json方式提交的，所以要加@RequestBody
    @PostMapping("/save")
    public CommonResp save(@Valid @RequestBody EbookSaveReq req){
        CommonResp resp = new CommonResp() ;
        this.ebookService.save(req) ;
        return  resp ;
    }

    @DeleteMapping("/delete/{id}")
    public CommonResp delete(@PathVariable Long id){
        CommonResp resp = new CommonResp() ;
        this.ebookService.delete(id) ;
        return resp ;
    }

    @PostMapping("/upload-image")
    public CommonResp uploadImage(MultipartFile file){
        String fileName = file.getOriginalFilename() ;
        String suffix = fileName.substring(fileName.lastIndexOf(".")) ; // 获取图片后缀，如 .jpg  .png
        // 图片重命名，正常情况下考虑用流水号生成器（如雪花算法），这里简单用 登录名+时间戳 来代替
        String currDateStr = new SimpleDateFormat("yyy-MM-dd-HH-mm-ss").format(new Date()) ;
        String fileNameNew = LoginUserContext.getUser().getLoginName() + "-" + currDateStr + suffix ;
        LOG.info("原封面图片名：{}，重命名为：{}", fileName, fileNameNew);
        // 将图片存储到临时文件夹，并将文件名返回给前端（后面save时需要前端上送）（tmp目录下，定时shell脚本更新，超过2天的文件进行清理）
        if(!FileUtil.saveFile(file, this.tempFilePath, fileNameNew)){
            throw new BusinessException(BusinessExceptionCode.SAVE_FILE_ERROR) ;
        }
        CommonResp resp = new CommonResp() ;
        resp.setContent(fileNameNew);
        return resp ;
    }

    // @RequestMapping上加入produces告诉Spring，我们要返回的MediaType是一个图片（image/jpeg），前端通过<img :src="url"/>请求该交易并回显图片
    @RequestMapping(value = "/load-image/{cover}", produces = MediaType.IMAGE_JPEG_VALUE)
    @ResponseBody
    public byte[] loadImage(@PathVariable String cover) {
        FileInputStream fis = null ;
        try{
            fis = new FileInputStream(new File(this.workFilePath + File.separator + cover));
            byte[] bytes = new byte[fis.available()];
            fis.read(bytes, 0, fis.available());
            return bytes;
        }catch (FileNotFoundException e){
            LOG.info("电子书封面图片：{}，不存在", cover) ;
        }catch (IOException e){
            LOG.info("电子书封面图片：{}，读取失败", cover) ;
        }finally {
            try {
                fis.close();
            } catch (Exception e) {
                LOG.info("Close InputStream Error!" + e.getMessage()) ;
            }
        }
        return null ;
    }

}
